#include "networkcontroller.h"
#include "config.h"
#include <QDebug>
#include <QThread>
#include <QJsonArray>
#include <QNetworkInterface>
#include <QDateTime>

// 常量定义
const quint16 NetworkController::DEFAULT_DISCOVERY_PORT = 8888;
const quint16 NetworkController::DEFAULT_DEVICE_PORT = 8889;
const int NetworkController::DEFAULT_TIMEOUT = 5000;
const int NetworkController::NETWORK_MAX_RETRY_COUNT = 5;
const QString NetworkController::DISCOVERY_MESSAGE = "HI3861_DISCOVERY_REQUEST";
const QString NetworkController::DEVICE_TYPE_HI3861 = "HI3861_DISPLAY";

NetworkController::NetworkController(QObject *parent)
    : QObject(parent)
    , m_udpSocket(new QUdpSocket(this))
    , m_networkManager(new QNetworkAccessManager(this))
    , m_discoveryTimer(new QTimer(this))
    , m_statusTimer(new QTimer(this))
    , m_displayWidth(ST7789_RESOLUTION_WIDTH)
    , m_displayHeight(ST7789_RESOLUTION_HEIGHT)
    , m_colorDepth(16)
    , m_isInitialized(false)
{
    initializeNetwork();
    
    // 设置定时器
    m_discoveryTimer->setInterval(30000); // 30秒发现一次设备
    m_statusTimer->setInterval(10000);    // 10秒检查一次状态
    
    connect(m_discoveryTimer, &QTimer::timeout, this, &NetworkController::discoverDevices);
    connect(m_statusTimer, &QTimer::timeout, this, &NetworkController::checkDeviceStatus);
    connect(m_udpSocket, &QUdpSocket::readyRead, this, &NetworkController::handleUdpResponse);
    
    // 启动定时器
    m_discoveryTimer->start();
    m_statusTimer->start();
    
    // 立即发现设备
    QTimer::singleShot(1000, this, &NetworkController::discoverDevices);
}

NetworkController::~NetworkController()
{
    if (m_udpSocket) {
        m_udpSocket->close();
    }
}

bool NetworkController::initializeNetwork()
{
    qDebug() << "初始化网络控制器...";
    
    // 绑定UDP套接字
    if (!m_udpSocket->bind(QHostAddress::Any, DEFAULT_DISCOVERY_PORT)) {
        qWarning() << "无法绑定UDP端口" << DEFAULT_DISCOVERY_PORT << ":" << m_udpSocket->errorString();
        // 尝试绑定到其他端口
        for (quint16 port = DEFAULT_DISCOVERY_PORT + 1; port < DEFAULT_DISCOVERY_PORT + 10; ++port) {
            if (m_udpSocket->bind(QHostAddress::Any, port)) {
                qDebug() << "成功绑定到UDP端口" << port;
                break;
            }
        }
        
        if (m_udpSocket->state() != QAbstractSocket::BoundState) {
            qCritical() << "无法绑定任何UDP端口";
            return false;
        }
    }
    
    m_isInitialized = true;
    qDebug() << "网络控制器初始化完成，UDP端口:" << m_udpSocket->localPort();
    
    return true;
}

bool NetworkController::addDevice(int deviceIndex, const QString &ip, quint16 port)
{
    QMutexLocker locker(&m_networkMutex);
    
    NetworkConfig config;
    config.deviceIP = ip;
    config.devicePort = port;
    config.timeout = DEFAULT_TIMEOUT;
    config.retryCount = MAX_RETRY_COUNT;
    
    m_devices[deviceIndex] = config;
    m_deviceStatus[deviceIndex] = false;
    
    qDebug() << "添加设备" << deviceIndex << "IP:" << ip << "端口:" << port;
    
    // 初始化设备
    return initializeDevice(deviceIndex);
}

bool NetworkController::removeDevice(int deviceIndex)
{
    QMutexLocker locker(&m_networkMutex);
    
    if (m_devices.contains(deviceIndex)) {
        m_devices.remove(deviceIndex);
        m_deviceStatus.remove(deviceIndex);
        m_lastResponse.remove(deviceIndex);
        
        qDebug() << "移除设备" << deviceIndex;
        emit deviceStatusChanged(deviceIndex, false);
        return true;
    }
    
    return false;
}

bool NetworkController::sendToDisplay(int displayIndex, const QByteArray &data)
{
    QMutexLocker locker(&m_networkMutex);
    
    if (!m_isInitialized) {
        emit networkError("网络控制器未初始化");
        return false;
    }
    
    if (!m_devices.contains(displayIndex)) {
        emit networkError(QString("设备%1未配置").arg(displayIndex));
        return false;
    }
    
    if (!m_deviceStatus.value(displayIndex, false)) {
        emit networkError(QString("设备%1离线").arg(displayIndex));
        return false;
    }
    
    QJsonObject command = createDisplayCommand(data);
    bool success = sendUdpCommand(displayIndex, command);
    
    if (success) {
        emit dataTransmitted(displayIndex, data.size());
        qDebug() << "向设备" << displayIndex << "发送" << data.size() << "字节显示数据";
    } else {
        emit networkError(QString("设备%1数据传输失败").arg(displayIndex));
    }
    
    return success;
}

bool NetworkController::sendUdpCommand(int deviceIndex, const QJsonObject &command)
{
    if (!m_devices.contains(deviceIndex)) {
        return false;
    }
    
    const NetworkConfig &config = m_devices[deviceIndex];
    QJsonDocument doc(command);
    QByteArray data = doc.toJson(QJsonDocument::Compact);
    
    QHostAddress address(config.deviceIP);
    qint64 sent = m_udpSocket->writeDatagram(data, address, config.devicePort);
    
    if (sent != data.size()) {
        qWarning() << "UDP数据发送不完整，设备" << deviceIndex 
                   << "发送:" << sent << "期望:" << data.size();
        return false;
    }
    
    return true;
}

bool NetworkController::sendHttpCommand(int deviceIndex, const QJsonObject &command)
{
    if (!m_devices.contains(deviceIndex)) {
        return false;
    }
    
    const NetworkConfig &config = m_devices[deviceIndex];
    QUrl url(QString("http://%1:%2/api/command").arg(config.deviceIP).arg(config.devicePort));
    
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("User-Agent", "RK3588-NetworkController");
    
    QJsonDocument doc(command);
    QByteArray data = doc.toJson();
    
    QNetworkReply *reply = m_networkManager->post(request, data);
    
    // 设置超时
    QTimer::singleShot(config.timeout, reply, [reply]() {
        if (reply->isRunning()) {
            reply->abort();
        }
    });
    
    connect(reply, &QNetworkReply::finished, this, &NetworkController::handleHttpResponse);
    
    return true;
}

QJsonObject NetworkController::createDisplayCommand(const QByteArray &data)
{
    QJsonObject command;
    command["type"] = "display";
    command["action"] = "update";
    command["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    
    // 将二进制数据转换为Base64编码
    QJsonObject displayData;
    displayData["format"] = "rgb565";
    displayData["width"] = m_displayWidth;
    displayData["height"] = m_displayHeight;
    displayData["data"] = QString(data.toBase64());
    displayData["size"] = data.size();
    
    command["display"] = displayData;
    
    return command;
}

QJsonObject NetworkController::createConfigCommand(const QString &param, const QVariant &value)
{
    QJsonObject command;
    command["type"] = "config";
    command["action"] = "set";
    command["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    
    QJsonObject config;
    config[param] = QJsonValue::fromVariant(value);
    command["config"] = config;
    
    return command;
}

QJsonObject NetworkController::createStatusCommand()
{
    QJsonObject command;
    command["type"] = "status";
    command["action"] = "get";
    command["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    
    return command;
}

void NetworkController::discoverDevices()
{
    // qDebug() << "开始设备发现..."; // 过于频繁，已禁用
    
    // 广播发现消息
    broadcastDiscovery();
}

void NetworkController::broadcastDiscovery()
{
    QJsonObject discovery;
    discovery["type"] = "discovery";
    discovery["action"] = "request";
    discovery["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    discovery["requester"] = "RK3588";
    discovery["looking_for"] = DEVICE_TYPE_HI3861;
    
    QJsonDocument doc(discovery);
    QByteArray data = doc.toJson(QJsonDocument::Compact);
    
    // 向所有网络接口的广播地址发送
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
    for (const QNetworkInterface &interface : interfaces) {
        if (interface.flags() & QNetworkInterface::IsUp &&
            interface.flags() & QNetworkInterface::CanBroadcast &&
            !(interface.flags() & QNetworkInterface::IsLoopBack)) {
            
            for (const QNetworkAddressEntry &entry : interface.addressEntries()) {
                if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
                    QHostAddress broadcast = entry.broadcast();
                    if (!broadcast.isNull()) {
                        m_udpSocket->writeDatagram(data, broadcast, DEFAULT_DEVICE_PORT);
                        // qDebug() << "广播发现消息到:" << broadcast.toString(); // 过于频繁，已禁用
                    }
                }
            }
        }
    }
}

void NetworkController::handleUdpResponse()
{
    while (m_udpSocket->hasPendingDatagrams()) {
        QByteArray data;
        QHostAddress sender;
        quint16 senderPort;
        
        data.resize(m_udpSocket->pendingDatagramSize());
        m_udpSocket->readDatagram(data.data(), data.size(), &sender, &senderPort);
        
        // 解析响应
        QJsonParseError error;
        QJsonDocument doc = QJsonDocument::fromJson(data, &error);
        
        if (error.error != QJsonParseError::NoError) {
            qWarning() << "JSON解析错误:" << error.errorString();
            continue;
        }
        
        QJsonObject response = doc.object();
        QString type = response["type"].toString();
        
        if (type == "discovery") {
            parseDiscoveryResponse(data, sender);
        } else if (type == "status") {
            // 处理状态响应
            int deviceIndex = response["device_index"].toInt(-1);
            if (deviceIndex >= 0 && m_devices.contains(deviceIndex)) {
                bool online = response["status"].toString() == "online";
                bool wasOnline = m_deviceStatus.value(deviceIndex, false);
                
                m_deviceStatus[deviceIndex] = online;
                m_lastResponse[deviceIndex] = QDateTime::currentDateTime();
                
                if (online != wasOnline) {
                    emit deviceStatusChanged(deviceIndex, online);
                    // qDebug() << "设备" << deviceIndex << "状态变更:" << (online ? "在线" : "离线"); // 过于频繁，已禁用
                }
            }
        }
    }
}

void NetworkController::parseDiscoveryResponse(const QByteArray &data, const QHostAddress &sender)
{
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
    
    if (error.error != QJsonParseError::NoError) {
        return;
    }
    
    QJsonObject response = doc.object();
    
    if (response["action"].toString() == "response" &&
        response["device_type"].toString() == DEVICE_TYPE_HI3861) {
        
        int deviceIndex = response["device_index"].toInt(-1);
        quint16 port = response["port"].toInt(DEFAULT_DEVICE_PORT);
        QString deviceName = response["device_name"].toString();
        
        if (deviceIndex >= 0) {
            // qDebug() << "发现Hi3861设备:" << deviceName 
            //          << "IP:" << sender.toString() 
            //          << "端口:" << port 
            //          << "索引:" << deviceIndex; // 过于频繁，已禁用
            
            // 自动添加设备
            if (!m_devices.contains(deviceIndex)) {
                addDevice(deviceIndex, sender.toString(), port);
                emit deviceDiscovered(sender.toString(), deviceIndex);
            }
        }
    }
}

void NetworkController::handleHttpResponse()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;
    
    QByteArray data = reply->readAll();
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    
    if (statusCode == 200) {
        qDebug() << "HTTP命令执行成功:" << data;
    } else {
        qWarning() << "HTTP命令执行失败，状态码:" << statusCode << "响应:" << data;
    }
    
    reply->deleteLater();
}

void NetworkController::checkDeviceStatus()
{
    for (int deviceIndex : m_devices.keys()) {
        QJsonObject statusCommand = createStatusCommand();
        sendUdpCommand(deviceIndex, statusCommand);
    }
}

bool NetworkController::pingDevice(int deviceIndex)
{
    if (!m_devices.contains(deviceIndex)) {
        return false;
    }
    
    QJsonObject pingCommand;
    pingCommand["type"] = "ping";
    pingCommand["action"] = "request";
    pingCommand["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    
    return sendUdpCommand(deviceIndex, pingCommand);
}

bool NetworkController::isDeviceOnline(int deviceIndex)
{
    return m_deviceStatus.value(deviceIndex, false);
}

QString NetworkController::getDeviceStatus(int deviceIndex)
{
    if (!m_devices.contains(deviceIndex)) {
        return "未配置";
    }
    
    bool online = m_deviceStatus.value(deviceIndex, false);
    if (online) {
        QDateTime lastResponse = m_lastResponse.value(deviceIndex);
        if (lastResponse.isValid()) {
            int secondsAgo = lastResponse.secsTo(QDateTime::currentDateTime());
            return QString("在线 (最后响应: %1秒前)").arg(secondsAgo);
        }
        return "在线";
    }
    
    return "离线";
}

bool NetworkController::initializeDevice(int deviceIndex)
{
    if (!m_devices.contains(deviceIndex)) {
        return false;
    }
    
    // 发送初始化配置
    configureDevice(deviceIndex);
    
    // 发送状态查询
    QJsonObject statusCommand = createStatusCommand();
    return sendUdpCommand(deviceIndex, statusCommand);
}

void NetworkController::configureDevice(int deviceIndex)
{
    // 发送显示配置
    QJsonObject resolutionCmd = createConfigCommand("resolution", 
        QJsonObject{{"width", m_displayWidth}, {"height", m_displayHeight}});
    sendUdpCommand(deviceIndex, resolutionCmd);
    
    QJsonObject colorDepthCmd = createConfigCommand("color_depth", m_colorDepth);
    sendUdpCommand(deviceIndex, colorDepthCmd);
    
    // qDebug() << "配置设备" << deviceIndex << "分辨率:" << m_displayWidth << "x" << m_displayHeight 
    //          << "颜色深度:" << m_colorDepth; // 过于频繁，已禁用
}

void NetworkController::setDisplayResolution(int width, int height)
{
    m_displayWidth = width;
    m_displayHeight = height;
    // qDebug() << "设置显示分辨率为:" << width << "x" << height; // 过于频繁，已禁用
    
    // 更新所有设备配置
    for (int deviceIndex : m_devices.keys()) {
        QJsonObject command = createConfigCommand("resolution", 
            QJsonObject{{"width", width}, {"height", height}});
        sendUdpCommand(deviceIndex, command);
    }
}

void NetworkController::setColorDepth(int bits)
{
    m_colorDepth = bits;
    // qDebug() << "设置颜色深度为:" << bits << "位"; // 过于频繁，已禁用
    
    // 更新所有设备配置
    for (int deviceIndex : m_devices.keys()) {
        QJsonObject command = createConfigCommand("color_depth", bits);
        sendUdpCommand(deviceIndex, command);
    }
}

void NetworkController::onDiscoveryTimeout()
{
    // qDebug() << "设备发现超时"; // 过于频繁，已禁用
} 